#include "DFCalculator.h"
#include "ui_DFCalculator.h"
#include "GraphTools.h"
#include "FrameMaker.h"
#include <QtGui/QMessageBox>

namespace DDAGui{
    extern DISPLAYMODE playMode ;

	extern void msg2File(const char* msg);

    extern void viewFitAll();   // this function is defined in Command.cpp
    extern void sleepQT(int seconds);   // this function is defined in BaseConfigs.h 
	extern void setFrameIdx(int idx); // in FrameMaker.cpp
	extern void updateRealTimeDisplacement(double value); // in FrameMaker.cpp
	extern void clearDisplacements(); // in FrameMaker.cpp
	extern void addMeasuredPointCoordinate4Idx(int pIdx, double x, double y); // in FrameMaker.cpp
	extern void initMeasuredPointCoords(int mpsNum, int framesNum); // in FrameMaker.cpp
}

using namespace DDAGui;
using namespace std;
//////////////////////////////////////
////  DDAPostplayer
//////////////////////////////////////
DFCalculator::DFCalculator(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::DFCalculator),
    _dfCalculator(NULL),
    _playSpeed(1),
    _ifRealTime(true),
    _maxDisplacement(1)

{
    ui->setupUi(this);
    playMode = DISPLAY_ACCUMULATION_DISPLACEMENT;
    initConnection();
    _frameMaker = new FrameMaker;
	msg2File("DFCalculator::DFCalculator done.");
}

DFCalculator::~DFCalculator()
{
    delete _frameMaker;
    delete ui;
}

void DFCalculator::setRealTime(int flag)
{
    if(flag==0)
        _ifRealTime= false;
    else
        _ifRealTime= true;
    ui->speedSpinBox->setEnabled(_ifRealTime);
    ui->radioDisplacement->setEnabled(_ifRealTime);
    ui->radioStress->setEnabled(_ifRealTime);
}

void DFCalculator::calcBtnPressed()
{
    if(ui->calcBtn->text()==QObject::tr("Calculate")){
        ui->calcBtn->setText(QObject::tr("Pause"));
        ui->speedSpinBox->setEnabled(false);
        ui->radioDisplacement->setEnabled(false);
        ui->radioStress->setEnabled(false);
        calc();
    }
    else{
        ui->calcBtn->setText(QObject::tr("Calculate"));
        ui->speedSpinBox->setEnabled(true);
        ui->radioDisplacement->setEnabled(true);
        ui->radioStress->setEnabled(true);
    }
}

void DFCalculator::speedChanged(int speed)
{
    _playSpeed = speed;
}

void DFCalculator::radioButtonDisplacementClicked()
{
    if(ui->radioDisplacement->isChecked())
        playMode = DISPLAY_ACCUMULATION_DISPLACEMENT;
}

void DFCalculator::radioButtonStressClicked()
{
    if(ui->radioStress->isChecked())
        playMode = DISPLAY_STRESS;

}

void DFCalculator::initPlay()
{
     if(!_dfCalculator)
         _dfCalculator = new DF();
     _dfCalculator->calculationInit();
     printf("Core calculator init done.\n");
 
	 msg2File("corecalculation init.\n");
     FrameData frame = _dfCalculator->getCurrentFrame();
     vector<int> schema = _dfCalculator->getSchema();
	 msg2File("prepare to init frame done.\n");
     printf("prepare to init frame done.\n");
	 msg2File("start reset FrameMaker.\n");

	 msg2File("start init.");
	 clearDisplacements(); // in FrameMaker.cpp
	 initMeasuredPointCoords(schema[3], schema[6]); // in FrameMaker.cpp
	 msg2File("init done.");

	 // update displacement and measured points
	 setFrameIdx(0);
// 	 updateRealTimeDisplacement(0); // in FrameMaker.cpp
	 std::vector<MeasuredPoint>& mps = frame.measuredPoints;
	 for( int i=0; i<mps.size(); i++)
		 addMeasuredPointCoordinate4Idx(i, mps[i].x, mps[i].y); // in FrameMaker.cpp

     _frameMaker->reset(frame , schema);
	 msg2File("reset FrameMaker done.\n");
     viewFitAll();
     printf("fist frame init done.\n");


     ui->stepSpinBox->setMaximum(schema.back());
     ui->progressBar->setMaximum(schema.back());
}

void DFCalculator::initConnection()
{
    QObject::connect(ui->speedSpinBox , SIGNAL(valueChanged(int)) , this , SLOT(speedChanged(int)));
    QObject::connect(ui->calcBtn , SIGNAL(pressed()) , this , SLOT(calcBtnPressed()));
    QObject::connect(ui->radioDisplacement , SIGNAL(toggled(bool)) , this , SLOT(radioButtonDisplacementClicked()));
    QObject::connect(ui->radioStress , SIGNAL(toggled(bool)) , this , SLOT(radioButtonStressClicked()));
}
bool DFCalculator::ifContinuePlay()
{
    return ui->calcBtn->text()=="Pause";
}

void DFCalculator::calc()
{
   while(_dfCalculator->hasNextStep()) 
   {
       if(!ifContinuePlay())
           break;
       _dfCalculator->calculate1Step();
       ui->stepSpinBox->setValue(_dfCalculator->getStepNumber());

	   // update displacement and measured points
	   FrameData frame = _dfCalculator->getCurrentFrame();
	   updateRealTimeDisplacement(frame.maxDisplacement); // in FrameMaker.cpp
	   std::vector<MeasuredPoint>& mps = frame.measuredPoints;
	   for( int i=0; i<mps.size(); i++)
		   addMeasuredPointCoordinate4Idx(i, mps[i].x, mps[i].y); // in FrameMaker.cpp


	   // if update frame
       if(_ifRealTime && _dfCalculator->getStepNumber()%_playSpeed==0)
       {
           if(_maxDisplacement<frame.maxDisplacement)
                _maxDisplacement = frame.maxDisplacement;
           _frameMaker->setScale(_maxDisplacement*1.1);
           _frameMaker->updateGraph(_dfCalculator->getCurrentFrame(), playMode);
           _soQtViewer->render();
           //sleepQT(0.1);
       }
       QApplication::instance()->processEvents();
   }
   if(!_dfCalculator->hasNextStep())
   {
       _dfCalculator->endCalculation();
       hide();
       QMessageBox msgBox;
       msgBox.setText("DDA analysis has already been done.");
       msgBox.exec();
   }
}
